home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: loop.C,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:54 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "semaphore.h"
- #include "latch.h"
- #include "link.h"
- #include "host.h"
- #include "bitvec.h"
- #include "bf.h"
- #include "disk.h"
- #include "volume.h"
- #include "threadstate.h"
- #include "msgvector.h"
- #include "msg_funcs.h"
- #include "timer.h"
- #include "thread_funcs.h"
- #include "disk_funcs.h"
- #include "server_util_funcs.h"
- #include "mr_extfuncs.h"
- #include "thread_globals.h"
- #include "msg_globals.h"
- #include "recover_globals.h"
- #include "stat_globals.h"
- #include "queue_consist.h"
-
- void
- loop ()
-
- {
- static TIMEVAL *ZeroTime = (TIMEVAL *)0;
- SELECTTIME SelectTimeStruct;
-
- register LINK *link;
- register TCB *tcb;
- static int numReady = 0;
- register int readyIndex;
-
-
- Active->state = THREAD_LOOP;
-
- for (;;) {
- # ifdef DEBUG
- checkMalloc();
- # endif DEBUG
-
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("in loop thread:%d", Active->id));
- SelectTime = ZeroTime; /* block indefinitely */
- #ifdef DEBUG
- loops++;
- #endif DEBUG
-
-
- /*
- * check to see if we are down to the last thread
- */
- if (Spare == NULL) {
- #ifdef DEBUG
- loop_spare++;
- #endif DEBUG
-
- /*
- * this will be made the spare thread
- */
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("returning:%d the spare thread", Active->id));
- SelectMask = AllMask;
- SelectRestrict = 0;
- Spare = Active;
- dispatch(THREAD_SPARE_TCB);
-
- } else {
-
- /*
- * check to see if there is a thread ready to run
- */
- if ((tcb = (TCB *) listDeq( &ReadyList )) != NULL) {
-
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("thread:%d off ready list", tcb->id));
-
- #ifdef DEBUG
- loop_ran_ready++;
- #endif DEBUG
- /*
- * switch to that thread
- */
- freeThread(Active);
- threadSwitch(tcb);
- threadRestart();
- }
- }
-
- /*
- * Check all the disk queues for potential work.
- */
- if( selectDisk() )
- continue;
-
- /*
- * selectDisk() found nothing in the queues, so do a select.
- */
-
- select_again:
- if(numReady == 0) {
- /*
- * We have no ready fds. Get a new list (mask)
- * of them by doing select again.
- */
- serv_sleeps++;
- ReadMask = SelectMask;
-
- AwakenedAThread = FALSE;
- /*
- * Tick might call WakeUp, which puts a thread
- * back on the ready queue. We'd like that thread
- * to get a chance to run before we do the next
- * select
- */
- if((SelectTimeStruct.tv_sec = ServerTimer.Tick(FALSE, TRUE)) == 0){
- SelectTime = ZeroTime;
- } else {
- SelectTime = &SelectTimeStruct;
- SelectTimeStruct.tv_usec = 0;
- }
- if(AwakenedAThread) {
- continue; /* for loop */
- }
-
- TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_2,
- ("thread:%d %s on select", Active->id,
- ((SelectTime==ZeroTime)? "blocking indefinitely":
- (SelectTime == &SelectTimeStruct)? "blocking w/ timeout":
- "polling")));
- /* polling might not be used anymore, but the
- * code for tracing it is kept here anyway
- */
- #ifdef hpux
- numReady = select(SelectBits, (int*)&ReadMask,
- #else
- numReady = select(SelectBits, (fd_set*)&ReadMask,
- #endif
- NULL, NULL, SelectTime);
- }
- if(numReady<0) {
- /*
- * See if the error was caused by an interupted select.
- */
- if (errno == EINTR) {
- /* Just try the select again */
- serv_sel_intrs++;
-
- numReady = 0;
- TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1,
- ("select interrupted: restart"));
- goto select_again;
- } else {
- SM_ERROR(TYPE_FATAL, errno);
- }
- }
- SM_ASSERT(LEVEL_1, Replies->willBlock == 1);
- Replies->willBlock = 0;
-
- TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1,
- ("returned from select %d sockets ready, ReadMask 0x%x",
- numReady, ReadMask));
-
- /*
- * If numReady is zero right away,
- * we did a poll (or timeout) instead of an indefinite select, and
- * nothing's ready to go, so check the queues again.
- */
- if(numReady == 0) {
- continue; /* for loop */
- }
-
- /*
- * OK, now numReady > 0.
- * do a round-robin through the ready fd mask,
- * giving priority to disk fds.
- */
- readyIndex = selectReceive( &ReadMask );
-
- TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1,
- ("socket fd=%d ready", readyIndex));
-
- /*
- * remove this link from the read mask so that
- * we will not visit it until we do another select.
- */
- numReady--;
- bic( &ReadMask, readyIndex );
-
- /*
- * switch based on the type of link
- */
- link = &(Links[readyIndex]);
- #ifdef DEBUG
- if(link->id != readyIndex) {
- fprintf(sm_ErrorStream, "LINK ID=%d, readyIndex %d / 0x%x\n",
- link->id, readyIndex, readyIndex);
- }
- SM_ASSERT(LEVEL_1, (link->id == readyIndex));
- #endif
- TRPRINT(TR_CL|TR_MSG , TR_LEVEL_1,
- (" link type(%d) for fd=%d\n", link->linkClass, link->id ));
- switch (link->linkClass) {
- case CL_DGRAM:
- sel_dgrams++;
-
- TRPRINT(TR_MSG, TR_LEVEL_2, ("dgrams"));
- serverReceive(link);
- break;
-
- case CL_CONNECT:
- sel_connects++;
-
- TRPRINT(TR_MSG, TR_LEVEL_2, ("connect"));
- clientConnect(link);
- break;
-
- case CL_DISK:
- sel_disks++;
-
- TRPRINT(TR_MSG, TR_LEVEL_2, ("disk"));
- diskReceive(link);
- break;
-
- case CL_TIMEDOUT:
- sel_clients++;
- TRPRINT(TR_MSG, TR_LEVEL_2, ("timed-out-client"));
- /* already freed the client link so just continue
- * the loop (same as doing a threadRestart)
- */
- link->linkClass = CL_UNUSED;
- TRPRINT(TR_MSG, TR_LEVEL_1,
- ("link:%d is now type %d", link->id, link->linkClass));
- break;
-
- case CL_CLIENT:
- sel_clients++;
-
- TRPRINT(TR_MSG, TR_LEVEL_2, ("client"));
- clientReceive(link);
- break;
-
- #ifdef MEDIA_RECOVERY
- case CL_MEDIA_RECOVERY:
- sel_media++;
- SM_ASSERT(LEVEL_1, MediaRecovery);
- mr_Receive(link);
- break;
- #endif MEDIA_RECOVERY
-
- case CL_STDOUT:
- case CL_STDERR:
- /* like clearLink, but don't close the file */
- bic( &(SelectMask), link->id);
- bic( &(AllMask), link->id);
- break;
-
- case CL_STDIN:
- sel_stdin++;
- #ifdef MEDIA_RECOVERY
- mr_Receive(link);
- #else MEDIA_RECOVERY
- terminal_input(link);
- #endif MEDIA_RECOVERY
- break;
-
-
- default:
- fprintf(sm_ErrorStream, "Unknown link type(%d) for fd=%d\n",
- link->linkClass, link->id );
- #ifdef DEBUG
- /* grot TODO : remove */
- fprintf(sm_ErrorStream, "was %d\n", link->address.sin_family);
- #endif DEBUG
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- break;
- } /* switch */
- } /* for */
- }
-